﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using Newtonsoft.Json.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace QbservableCore.Serialization
{
    public class DefaultQbservableConvention : IQbservableConvention
    {
        private static readonly Lazy<DefaultQbservableConvention> _lazyInstance =
            new Lazy<DefaultQbservableConvention>(() => new DefaultQbservableConvention());

        #region Ctor

        private DefaultQbservableConvention()
        {

        }

        #endregion // Ctor

        #region Instance

        /// <summary>
        /// Gets a singleton instance.
        /// </summary>
        /// <value>
        /// The instance.
        /// </value>
        public static IQbservableConvention Instance { get { return _lazyInstance.Value; } }

        #endregion // Instance

        #region IQbservableConventionMapper Members

        /// <summary>
        /// Distinct Mapper Key.
        /// </summary>
        /// <value>
        /// The mapper key.
        /// </value>
        public string ConventionKey
        {
            get { return "Default"; }
        }


        /// <summary>
        /// Maps the ExpressionType to convention.
        /// </summary>
        /// <param name="expType"></param>
        /// <returns></returns>
        public string FromExpressionTypeToConvention(ExpressionType expType)
        {
            return expType.ToString();
        }

        /// <summary>
        /// Maps System.Type to convention.
        /// </summary>
        /// <param name="t">The System.Type</param>
        /// <returns></returns>
        public string FromTypeToConvention(Type t)
        {
            string asmName = t.Assembly.FullName;
            string typeName = t.FullName;
            return string.Format("{0}~{1}", asmName, typeName);
        }

        /// <summary>
        /// Maps convention to type.
        /// </summary>
        /// <param name="convention"></param>
        /// <returns></returns>
        public Type FromConventionToType(string convention)
        {
            string[] asmAndType = convention.Split('~');
            var asm = Assembly.Load(asmAndType[0]);
            var retType = asm.GetType(asmAndType[1]);
            return retType;
        }

        /// <summary>
        /// Maps the key to convention.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string FromKeyToConvention(string key)
        {
            return "#" + key;
        }

        /// <summary>
        /// Maps the convention to key.
        /// </summary>
        /// <param name="convention"></param>
        /// <returns></returns>
        public string FromConventionToKey(string convention)
        {
            return convention.Substring(1);
        }

        #endregion // IQbservableConventionMapper Members
    }
}
